using System;
using System.Collections.Generic;
using System.Text;
using Decav.Reality;
using System.Net.Mail;
using Decav.Data;
using Decav.Gatsb.Data;
using Decav.Gatsb.Security;

namespace Decav.Gatsb
{
    /// <summary>
    /// Defines a user of the Gatsb system, and their basic profile information.
    /// </summary>
    [Serializable]
    public class User
    {
        private User(Guid id, EmailAddress email, PhoneNumber phoneNumber, TelephoneServiceProvider provider)
        {
            if (email == null)
                throw new ArgumentNullException("email");

            if (provider == null)
                throw new ArgumentNullException("provider");

            _id = Guid.NewGuid();
            _email = email;
            _mobilePhoneNumber = phoneNumber;
            _telephoneProvider = provider;
        }

        protected User(DataRecordAdapter adapt)
        {
            if (adapt == null)
                throw new ArgumentNullException("adapt");

            _id = adapt.GetGuid("UserId");
            _email = new EmailAddress(adapt.GetString("Email"));

            string nameString = adapt.GetString("Name");
            if (nameString == null || nameString.Length == 0)
                _name = PersonName.Empty;
            else
                _name = PersonName.Parse(nameString);

            _mobilePhoneNumber = new PhoneNumber(adapt.GetString("MobileTel"));
            _occupation = adapt.GetString("Occupation");

            string smsemail = adapt.GetString("SmsEmailAlternate");
            if (smsemail != null && smsemail.Length > 0)
                _alternateSmsAddress = new EmailAddress(adapt.GetString("SmsEmailAlternate"));

            string state = adapt.GetString("State");
            _state = state == null ? UsState.Empty : UsState.FromPostalCode(state);

            _postalCode = adapt.GetString("PostalCode");
            _city = adapt.GetString("City");
            _telephoneProvider = TelephoneServiceProvider.GetProvider(adapt.GetString("TelephoneServiceProvider"));

            _profilePrivacy = (PrivacyPermissionLevel)adapt.GetInt32("ProfilePermissions");
            _locationPrivacy = (PrivacyPermissionLevel)adapt.GetInt32("LocationPermissions");
            _defaultPostPrivacy = (PrivacyPermissionLevel)adapt.GetInt32("DefaultPostPermissions");
            _requestingUserCanSeeProfile = adapt.GetBoolean("RequesterCanSeeProfile");
            _friendship = (FriendshipStatus)adapt.GetInt32("AreFriends");
        }

        private EmailAddress _alternateSmsAddress;
        private Guid _id;
        private EmailAddress _email;
        private PersonName _name;
        private PhoneNumber _mobilePhoneNumber;
        private string _occupation;
        private PrivacyPermissionLevel _profilePrivacy = PrivacyPermissionLevel.Friends;
        private PrivacyPermissionLevel _locationPrivacy = PrivacyPermissionLevel.Friends;
        private PrivacyPermissionLevel _defaultPostPrivacy = PrivacyPermissionLevel.Public;
        private UsState _state;
        private string _postalCode;
        private string _city;
        private bool _requestingUserCanSeeProfile = true;
        private TelephoneServiceProvider _telephoneProvider;
        private FriendshipStatus _friendship;

        /// <summary>
        /// Creates a new <see cref="User"/> object that can be saved into the database for the new user.
        /// </summary>
        /// <param name="email">The email address of the user.</param>
        /// <param name="phoneNumber">The users phone number.</param>
        /// <param name="provider">The telephone provider of the user.</param>
        /// <returns>The user.</returns>
        public static User CreateNewUser(EmailAddress email, PhoneNumber phoneNumber, TelephoneServiceProvider provider)
        {
            return new User(Guid.NewGuid(), email, phoneNumber, provider);
        }

        /// <summary>
        /// Gets or sets an email address that can be used as an alternate to the <see cref="MobleTelephoneNumber"/> and
        /// service provider.  This is sometimes the sending email account from providers like Verizon.
        /// </summary>
        public EmailAddress AlternateSmsAddress
        {
            get
            {
                return _alternateSmsAddress;
            }
            set
            {
                _alternateSmsAddress = value;
            }
        }

        /// <summary>
        /// Gets the users unique identifier.
        /// </summary>
        public Guid Id
        {
            get
            {
                return _id;
            }
        }

        /// <summary>
        /// Gets the users email address.
        /// </summary>
        public EmailAddress Email
        {
            get
            {
                return _email;
            }
            set
            {
                _email = value;
            }
        }

        /// <summary>
        /// Gets or sets the users name.
        /// </summary>
        public PersonName Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }

        /// <summary>
        /// Gets or sets the users mobile telephone number
        /// </summary>
        public PhoneNumber MobilePhoneNumber
        {
            get
            {
                return _mobilePhoneNumber;
            }
            set
            {
                _mobilePhoneNumber = value;
            }
        }

        /// <summary>
        /// Gets or sets the description of the users occupation.
        /// </summary>
        public string Occupation
        {
            get
            {
                return _occupation;
            }
            set
            {
                _occupation = value;
            }
        }

        /// <summary>
        /// Gets or sets the postal code in which the user resides.
        /// </summary>
        public string PostalCode
        {
            get
            {
                return _postalCode;
            }
            set
            {
                _postalCode = value;
            }
        }

        /// <summary>
        /// Gets or sets the city in which the user resides in.
        /// </summary>
        public string City
        {
            get
            {
                return _city;
            }
            set
            {
                _city = value;
            }
        }

        /// <summary>
        /// Gets or sets the state in which the user resides.
        /// </summary>
        public UsState State
        {
            get
            {
                return _state;
            }
            set
            {
                _state = value;
            }
        }

        /// <summary>
        /// Gets or sets the level of permissions required to view the users profile.
        /// </summary>
        public PrivacyPermissionLevel ProfilePrivacy
        {
            get
            {
                return _profilePrivacy;
            }
            set
            {
                _profilePrivacy = value;
            }
        }

        /// <summary>
        /// Gets or sets the level of permissions required to view the users location.
        /// </summary>
        public PrivacyPermissionLevel LocationPrivacy
        {
            get
            {
                return _locationPrivacy;
            }
            set
            {
                _locationPrivacy = value;
            }
        }

        /// <summary>
        /// Gets or sets the default permissions used when creating a new post.
        /// </summary>
        public PrivacyPermissionLevel DefaultPostPrivacy
        {
            get
            {
                return _defaultPostPrivacy;
            }
            set
            {
                _defaultPostPrivacy = value;
            }
        }

        /// <summary>
        /// Gets whether or not the user that requested the <see cref="User"/> information can see
        /// details about this user.
        /// </summary>
        public bool RequestingUserCanSeeProfile
        {
            get
            {
                if (GatsbPrincipal.IsAuthenticated && GatsbPrincipal.Current.Identity.UserId == Id)
                    return true;

                return _requestingUserCanSeeProfile;
            }
        }

        /// <summary>
        /// Gets whether or not the <see cref="Friendship"/> is a mutual friendship.
        /// </summary>
        public bool FriendsWithRequester
        {
            get
            {
                return _friendship == FriendshipStatus.MutualFriends;
            }
        }

        /// <summary>
        /// Gets the status of the friendship with the requester.
        /// </summary>
        public FriendshipStatus Friendship
        {
            get
            {
                return _friendship;
            }
        }

        /// <summary>
        /// Gets or sets the mobile telephone service provider that the user uses.
        /// </summary>
        public TelephoneServiceProvider TelephoneServiceProvider
        {
            get
            {
                return _telephoneProvider;
            }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
        

                _telephoneProvider = value;
            }
        }
    }
}
